package com.time.workbench.efficient.util;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.time.workbench.core.entity.base.Result;
import com.time.workbench.efficient.config.GitConfig;
import com.time.workbench.efficient.entity.vo.GitCommitVO;
import com.time.workbench.efficient.entity.vo.GiteeBranchVO;
import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
public class GiteeUtil extends GItAbstractUtil {

    /**
     * 分支
     */
    private final String branches = "/api/v5/repos/{}/{}/branches";
    /**
     * commit
     */
    private final String commits = "/api/v5/repos/{}/{}/commits";

    /**
     * pulls
     */
    private final String pulls = "/api/v5/repos/{}/{}/pulls";
    /**
     * review
     */
    private final String review = "/api/v5/repos/{}/{}/pulls/{}/review";
    /**
     * test
     */
    private final String test = "/api/v5/repos/{}/{}/pulls/{}/test";
    /**
     * merge
     */
    private final String merge = "/api/v5/repos/{}/{}/pulls/{}/merge";

    /**
     * 获取所有分支
     * https://gitee.com/api/v5/swagger#/getV5ReposOwnerRepoBranches
     *
     * @return
     */
    @Override
    public List<String> branchAll() {
        List<String> ownerRepo = getOwnerRepo();
        String result = getMethodGit(StrUtil.format(branches, ownerRepo.get(0), ownerRepo.get(1)), null);
        List<GiteeBranchVO> giteeBranchVOS = JSON.parseArray(result, GiteeBranchVO.class);
        return giteeBranchVOS.stream().map(GiteeBranchVO::getName).collect(Collectors.toList());
    }

    /**
     * 获取所有commit
     * https://gitee.com/api/v5/swagger#/getV5ReposOwnerRepoCommits
     *
     * @return
     */
    @Override
    public List<GitCommitVO> commitAll(String branch) {
        List<String> ownerRepo = getOwnerRepo();
        HashMap<String, Object> paramMap = new HashMap<>();
        paramMap.put("sha", branch);
        paramMap.put("page", 1);
        paramMap.put("per_page", 20);
        String result = getMethodGit(StrUtil.format(commits, ownerRepo.get(0), ownerRepo.get(1)), paramMap);
        JSONArray array = JSONArray.parseArray(result);
        return array.stream().map(item -> {
            JSONObject commit = (JSONObject) item;
            GitCommitVO gitCommitVO = new GitCommitVO();
            gitCommitVO.setCommitId(commit.getString("sha"));
            gitCommitVO.setCommitMessage(commit.getJSONObject("commit").getString("message"));
            gitCommitVO.setAuthorName(commit.getJSONObject("commit").getJSONObject("committer").getString("name"));
            gitCommitVO.setDate(commit.getJSONObject("commit").getJSONObject("committer").getString("date"));
            gitCommitVO.setEmail(commit.getJSONObject("commit").getJSONObject("committer").getString("email"));
            gitCommitVO.setHtmlUrl(commit.getString("html_url"));
            return gitCommitVO;
        }).collect(Collectors.toList());
    }


    /**
     * 创建分支
     * https://gitee.com/api/v5/swagger#/postV5ReposOwnerRepoBranches
     *
     * @param oldBranch
     * @param newBranch
     * @return
     */
    @Override
    public Result<String> createBranch(String oldBranch, String newBranch) {
        List<String> ownerRepo = getOwnerRepo();
        HashMap<String, Object> paramMap = new HashMap<>();
        paramMap.put("refs", oldBranch);
        paramMap.put("branch_name", newBranch);
        String result = postMethodGit(StrUtil.format(branches, ownerRepo.get(0), ownerRepo.get(1)), paramMap);
        JSONObject resultObject = JSON.parseObject(result);
        String resultBranchName = resultObject.getString("name");
        if (StrUtil.isEmpty(resultBranchName)) {
            return Result.fail(resultObject.getString("message"));
        }
        return Result.success("", resultBranchName);
    }

    @Override
    public Result<Integer> createPR(String title, String sourceBranch, String targetBranch, boolean isDeleteSource) {
        List<String> ownerRepo = getOwnerRepo();
        HashMap<String, Object> paramMap = new HashMap<>();
        paramMap.put("title", title);
        paramMap.put("head", sourceBranch);
        paramMap.put("base", targetBranch);
        paramMap.put("prune_source_branch", isDeleteSource);
        String result = postMethodGit(StrUtil.format(pulls, ownerRepo.get(0), ownerRepo.get(1)), paramMap);
        JSONObject resultObject = JSON.parseObject(result);
        Integer number = resultObject.getInteger("number");
        String message = resultObject.getString("message");
        if (number == null) {
            return Result.fail(message);
        }
        return Result.success("", number);
    }

    @Override
    public Result<String> review(Integer number) {
        List<String> ownerRepo = getOwnerRepo();
        HashMap<String, Object> paramMap = new HashMap<>();
        paramMap.put("force", true);
        postMethodGit(StrUtil.format(review, ownerRepo.get(0), ownerRepo.get(1), number), paramMap);
        return Result.success();
    }

    @Override
    public Result<String> test(Integer number) {
        List<String> ownerRepo = getOwnerRepo();
        HashMap<String, Object> paramMap = new HashMap<>();
        paramMap.put("force", true);
        postMethodGit(StrUtil.format(test, ownerRepo.get(0), ownerRepo.get(1), number), paramMap);
        return Result.success();
    }

    @Override
    public Result<String> merge(Integer number, boolean isDeleteSource) {
        List<String> ownerRepo = getOwnerRepo();
        HashMap<String, Object> paramMap = new HashMap<>();
        paramMap.put("prune_source_branch", isDeleteSource);
        putMethodGit(StrUtil.format(merge, ownerRepo.get(0), ownerRepo.get(1), number), paramMap);
        return Result.success();
    }

    @Override
    public void closeMergeRequest(Integer number) {

    }


    private String getMethodGit(String uri, HashMap<String, Object> paramMap) {
        if (paramMap == null) paramMap = new HashMap<>();
        paramMap.put("access_token", gitConfig.getGiteeToken());
        log.info("gitee method:get url:{} 请求:{}", gitConfig.getGiteeUrl() + uri, JSON.toJSONString(paramMap));
        String body = HttpRequest.get(gitConfig.getGiteeUrl() + uri).form(paramMap).execute().body();
        log.info("gitee method:get url:{} 响应:{}", gitConfig.getGiteeUrl() + uri, body);
        return body;
    }

    private String postMethodGit(String uri, HashMap<String, Object> paramMap) {
        if (paramMap == null) paramMap = new HashMap<>();
        paramMap.put("access_token", gitConfig.getGiteeToken());
        log.info("gitee method:post url:{} 请求:{}", gitConfig.getGiteeUrl() + uri, JSON.toJSONString(paramMap));
        String body = HttpRequest.post(gitConfig.getGiteeUrl() + uri).timeout(-1).body(JSON.toJSONString(paramMap)).execute().body();
        log.info("gitee method:post url:{} 响应:{}", gitConfig.getGiteeUrl() + uri, body);
        return body;
    }

    private String putMethodGit(String uri, HashMap<String, Object> paramMap) {
        if (paramMap == null) paramMap = new HashMap<>();
        paramMap.put("access_token", gitConfig.getGiteeToken());
        log.info("gitee method:put url:{} 请求:{}", gitConfig.getGiteeUrl() + uri, JSON.toJSONString(paramMap));
        String body = HttpRequest.put(gitConfig.getGiteeUrl() + uri).timeout(-1).body(JSON.toJSONString(paramMap)).execute().body();
        log.info("gitee method:put url:{} 响应:{}", gitConfig.getGiteeUrl() + uri, body);
        return body;
    }

    private List<String> getOwnerRepo() {
        List<String> ownerRepo = getUriArray();
        StringBuilder owner = new StringBuilder();
        for (int i = 0; i < ownerRepo.size() - 1; i++) {
            owner.append(ownerRepo.get(i));
        }
        String repo = ownerRepo.get(ownerRepo.size() - 1);
        return CollectionUtil.newArrayList(owner.toString(), repo);
    }
}
